import { CanvasTexture, Color, Group, Mesh, Vector2 } from "three";
import { CqkjMap } from "../Basic/CqkjMap";
import { FixAxisSprite, FixAxisSpriteMaterial } from "../Basic/FixAxisSprite";
import { MapElement, MapElementOption } from "../Basic/MapElement";
import { setValue } from "../Util/common";
import { MATERIALPLACEHOLDER, PROJECTION, UNITBOX, ZERO2, ZERO3 } from "../Util/static";

const ACALE = new Vector2(0.02, 0.02)
const CENTER = new Vector2(0.5, 0.5)

const image = new Image();
image.src =
  "";
const texture = new CanvasTexture(image);

const materials = [createMaterial(0x94CCB1), createMaterial(0x6CF8AC), createMaterial(0xFFD43A), createMaterial(0xFF3A3A)]

export interface AirportOption extends MapElementOption {
  lon: number;
  lat: number;
  alt: number;
  risk: number;
  onMouseEnter: () => void
  onMouseLeave: () => void
  onClick: () => void
}

export class Airport extends MapElement<AirportOption>{

  get icon() {
    return this.root.children[0] as FixAxisSprite
  }
  get box() {
    return this.root.children[1] as Mesh
  }

  readonly root = new Group()

  get show(): boolean {
    return this.option.show
  }
  set show(val: boolean) {
    setValue(this.option, 'show', val, () => {
      this.root.visible = val
    })
  }

  get risk() {
    return this.option.risk
  }

  set risk(val) {
    setValue(this.option, 'risk', val, () => {
      this.icon.material = materials[val]
    })
  }

  constructor(map: CqkjMap, option: AirportOption) {
    super(map, option)
    const { root } = this
    const x = PROJECTION.lonToX(option.lon)
    const y = PROJECTION.latToY(option.lat)
    const z = PROJECTION.altToZ(option.alt)
    root.position.set(x, y, z)
    const sprite = new FixAxisSprite(materials[option.risk])
    sprite.renderOrder=50
    root.add(sprite)

    const box = new Mesh(UNITBOX,MATERIALPLACEHOLDER)
    box.layers.enable(1)
    box.userData.onClick = option.onClick
    box.userData.onMouseLeave = option.onMouseLeave
    box.userData.onMouseEnter = option.onMouseEnter
    root.add(box)
    map.scene.add(root)
    map.show&&this.onAfterViewChange()
  }

  onAfterViewChange(): void {
    const { map } = this
    const scale = 24 * map.stage.control.getDistance() / map.dom.offsetHeight
    this.box.scale.set(scale, scale, scale)
  }

  onDestroy(): void {
    this.map.scene.remove(this.root)
  }

  focus() {
    const { map, root } = this
    map.zoomTo(root.position, 500000)
  }

}


function createMaterial(color: number) {
  return new FixAxisSpriteMaterial({
    size: ZERO2,
    scale: ACALE,
    axis: "",
    center: CENTER,
    direction: ZERO3,
    uniforms: {
      u_color: {
        value: new Color(color)
      },
      u_texture: {
        value: texture,
      }
    },
    fragmentShader: `
    varying vec2 v_uv;
    uniform vec3 u_color;
    uniform sampler2D u_texture;
    void main() { 
      gl_FragColor = texture2D(u_texture,v_uv)*vec4(u_color,1.0);
    }
    `,
  })
}